home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / pcw.zip / INT24C.C < prev    next >
C/C++ Source or Header  |  1991-10-20  |  10KB  |  292 lines

  1. /**********************************************************/
  2. /* File Id.                  Int24c.C.                    */
  3. /* Author.                   Stan Milam.                  */
  4. /* Date Written.             11/05/89.                    */
  5. /*                                                        */
  6. /*          (c) Copyright 1989-90 by Stan Milam           */
  7. /*                                                        */
  8. /* Comments: This code will be responsible for installing */
  9. /* a Critical Interrupt Handler and handling of the crit- */
  10. /* ical interrupt.  The Interrupt code should check to see*/
  11. /* if a window can be displayed, set the window colors,   */
  12. /* check the error to see if disk or device error. If disk*/
  13. /* error display error message using subscript.  If device*/
  14. /* error try to determine device name and display in menu */
  15. /* title.                                                 */
  16. /* Research Material:                                     */
  17. /*   PC Tech Magazine,April 1987,Exception Handling       */
  18. /*   The MS-DOS Encycolpedia.                             */
  19. /**********************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <dos.h>
  25. #include "pcw.i"
  26. #include "pcwproto.h"
  27.  
  28. /* Function Declarations */
  29.  
  30. #if __ZTC__
  31. #define interrupt
  32.  
  33. void far *getvect( int nbr ) {
  34.  
  35.     union  REGS  regs;
  36.     struct SREGS sregs;
  37.  
  38.     regs.h.ah = (char) 0x35;
  39.     regs.h.al = (char) nbr;
  40.     int86x(0x21,®s,®s,&sregs);
  41.     return ( MK_FP(sregs.es, regs.x.bx) );
  42. }
  43.  
  44. void setvect( int nbr, void far *isr ) {
  45.  
  46.     union  REGS  regs;
  47.     struct SREGS sregs;
  48.  
  49.     regs.h.ah = 0x25;
  50.     regs.h.al = (char) nbr;
  51.     regs.x.dx = FP_OFF(isr);
  52.     sregs.ds  = FP_SEG(isr);
  53.     int86x(0x21,®s,®s,&sregs);
  54. }
  55.  
  56. void (far *old_int24)(void);
  57. #endif
  58.  
  59. #ifdef MSC
  60. void (interrupt far *old_int24)(void);
  61. #endif
  62. #ifdef __TURBOC__
  63. void interrupt (far *old_int24)(void);
  64. #endif
  65. #ifdef __POWERC
  66. void interrupt (far *old_int24)(void);
  67. #endif
  68. extern void far interrupt Int24(void);
  69. int  far Critical_Interrupt(int ax, int di, char far *device);
  70. void far _Save_ES_DS_(void);
  71.  
  72. /*            Local Fucntion Declarations             */
  73.  
  74. static void open_window(int ur, int uc, int lr, int lc);
  75. static void close_window(int ur, int uc,int lr, int lc);
  76.  
  77. typedef struct {                       /* Device Driver Header */
  78.     int  next_driver_offset;
  79.     int  next_driver_segment;
  80.     int  attribute;
  81.     int  strategy_offset;
  82.     int  interrupt_offset;
  83.     char device_name[8];               /* Only if character device */
  84. }DEVHDR;
  85.  
  86. /* For Disk Block Device Errors */
  87.  
  88. static char *err_titles[] = {
  89.    " Diskette is Write Protected ",
  90.    " Invalid Disk Drive Number ",
  91.    " Disk Drive is Not Ready ",
  92.    " Unknown Device Command ",
  93.    " CRC Error ",
  94.    " Bad Request Structure Length ",
  95.    " Disk Seek Error ",
  96.    " Unknown Disk Media ",
  97.    " Disk Sector Not Found ",
  98.    " Printer Out of Paper ",
  99.    " Device Write Error ",
  100.    " Device Read Error ",
  101.    " General Error "," "," ",
  102.    " Invalid Disk Changing "
  103. };
  104.  
  105. static char *disk_err_msg[] = {
  106.    "A critical interrupt has occured and",
  107.    "DOS has indicated the  above problem",
  108.    "with a  disk  drive.  Please  choose",
  109.    "from the menu  actions listed.      ",
  110.    NULL
  111. };
  112.  
  113. static char *non_disk_err[] = {
  114.    "A critical interrupt  has occured and",
  115.    "DOS has indicated the above  problem.",
  116.    "Please refer to the error message and",
  117.    "choose from the menu actions listed. ",
  118.    NULL
  119. };
  120.  
  121. static char *err_menu[] = {
  122.     "1. Ignore the Error (Not Recommended)",
  123.     "2. Retry the Operation (Try Twice)   ",
  124.     "3. Abort the Program (Last Resort)   ",
  125.     "4. Fail the Operation (Better than 3)",
  126.     (char *) NULL
  127. };
  128.  
  129. char far *_int24buf_;                   /* To hold screen contents */
  130.  
  131. /**********************************************************/
  132. /*                       set_int24()                      */
  133. /*                                                        */
  134. /* Set INT 24 to point to our assembler routine, but first*/
  135. /* save the address of the old interrupt handler to call  */
  136. /* it if we need to.                                      */
  137. /**********************************************************/
  138.  
  139. int set_int24(void) {
  140.  
  141.    _int24buf_ = (char far *) malloc(1148);      /* Malloc memory for window */
  142.    if (_int24buf_ == (char far *) NULL) return(0); /* Return if no memory */
  143. #ifdef MSC
  144.    old_int24 = _dos_getvect(0x24);              /* Get old int24 address */
  145.    _dos_setvect(0x24,Int24);                    /* Set Int 24 to point to */
  146. #else                                           /* Our code */
  147.    old_int24 = getvect(0x24);
  148.    setvect(0x24, Int24);
  149. #endif
  150. #ifdef __POWERC
  151.    _Save_ES_DS_();                              /* Save Data & Extra Seg */
  152. #endif
  153. return(1);
  154. }
  155.  
  156. /**********************************************************/
  157. /*                   Critical_Interrupt                   */
  158. /*                                                        */
  159. /* This routine is called by the Assembler routine Int24. */
  160. /* It will use the information passed to it to determine  */
  161. /* if the error was a disk error or a device error.  If a */
  162. /* device error we must determine if the device was a     */
  163. /* character device and display its name otherwise if it  */
  164. /* was a block device (has no name) we simply display a   */
  165. /* message stating " Block Device Error ".  If the error  */
  166. /* was a disk error we display the message subscripted    */
  167. /* the value in Di and display the drive passed in the    */
  168. /* 8 lower bits of Ax.  Pop up a menu and wait for user   */
  169. /* response in all cases. Return value in AX.             */
  170. /* If the return value in Ax is -1 the Assembler routine  */
  171. /* will restore the registers and call the original INT 24*/
  172. /* handler.                                               */
  173. /**********************************************************/
  174.  
  175. int far Critical_Interrupt(int ax, int di, char far *device) {
  176.  
  177.    char **msg;
  178.    char *wrkptr;
  179.    int mxr, mxc;
  180.    DEVHDR devhdr;
  181.    int  uc = 20, lc = 60;
  182.    int  tfclr = BLACK, mfclr = BLACK;
  183.    static char tmsg[38], dskmsg[31];
  184.    int  choice, err_code, drive;
  185.  
  186.    if (chk_video_state(&mxr, &mxc)) {       
  187.       if (_int24buf_ == (char far *) NULL) return(-1);
  188.       if ( ax < 0) {
  189.          farcopy((void far *) &devhdr, device,sizeof(devhdr)); 
  190.          if (devhdr.attribute < 0) {
  191.             wrkptr = strchr(devhdr.device_name,32);
  192.             if (wrkptr != NULL) {
  193.                wrkptr++;
  194.                *wrkptr = 0;
  195.             }
  196.             strcpy(tmsg," Error In Device: ");
  197.             strncat(tmsg,devhdr.device_name,8);
  198.          }
  199.          else {
  200.             if (ax & 0x0200) strcpy(tmsg," Bad Memory Image of F.A.T. ");
  201.             else strcpy(tmsg, " Block Device Error ");
  202.          }
  203.          msg = non_disk_err;                   /* Use non disk message */
  204.          memset(dskmsg, '\0', 31);             /* Clear & set disk message */
  205.          memset(dskmsg, 196, 30);
  206.       }
  207.       else {                                   /* Disk Error */
  208.          err_code = di & 0x00ff;               
  209.          drive    = (ax & 0x00ff) + 65;        
  210.          msg = disk_err_msg;                   /* Use disk error message */
  211.          strcpy(tmsg, err_titles[err_code]);   /* Use table of error msgs */
  212.          strcpy(dskmsg,"Error in Drive %c:");  /* Use disk message */
  213.       }
  214.  
  215. /* Build the window, sound the alarm, and wait for user response */
  216.  
  217.       if (mxc == 40) {                      /* Check max rows and adjust */
  218.          uc = 1;
  219.          lc = 40;
  220.       }
  221.       if (_monitor == COLOR) {              /* Check for Color video */
  222.          tfclr = BLUE;                      /* And adjust if it is */
  223.          mfclr = RED;
  224.       }
  225.       open_window(6,uc,19,lc);
  226.       qputs(6,(mxc/2)-(strlen(tmsg)/2),tfclr,LIGHTGRAY,tmsg);
  227.       q_block_write(7,uc+2,BLACK,LIGHTGRAY,err_menu);
  228.       qprintf(12,CENTER,mfclr,LIGHTGRAY,dskmsg,drive);
  229.       q_block_write(14,uc+2,BLACK,LIGHTGRAY,msg);
  230.       _sound(880); rest(9); _nosound();
  231.       do {
  232.          choice = readkey();
  233. /*         if (choice == 0) choice = readkey() + 128; */
  234.          choice -= 49;
  235.       } while (choice < 0 || choice > 3);
  236.       close_window(6,uc,19,lc);
  237.       return(choice);
  238.    }
  239.    else return(-1);                    /* Call Original Int 24 */
  240. }
  241.  
  242. /**********************************************************/
  243. /*                      open_window                       */
  244. /*                                                        */
  245. /* Code to save screen image, color the window, draw the  */
  246. /* the border.                                            */
  247. /**********************************************************/
  248.  
  249. static void open_window(int ur, int uc, int lr, int lc) {
  250.  
  251.     int far  *scrnptr;
  252.     unsigned offset, scrnseg;
  253.     int      rows, cols, page, pagesize;
  254.     int      bfclr;
  255.  
  256.     rows     = (lr - ur) + 1;
  257.     cols     = (lc - uc) + 1;
  258.     page     = getpage();
  259.     pagesize = getpagesize();
  260.     scrnseg  = getscrnseg();
  261.     offset   = MK_SCRNOFF(ur,uc);
  262.     scrnptr  = (int far *) MK_FP(scrnseg,offset);
  263.     SaveScrn(rows, cols, scrnptr, _int24buf_);
  264.     qfill(ur, uc, lr, lc,LIGHTGRAY, LIGHTGRAY, 32);
  265.     bfclr = (_monitor == COLOR) ? BROWN : BLACK;
  266.     bordercolor(bfclr,LIGHTGRAY);
  267.     setborder(DOUBLESIDES);
  268.     qbox(ur,uc,lr,lc);
  269. }
  270.  
  271. /**********************************************************/
  272. /*                      close_window                      */
  273. /*                                                        */
  274. /* Logic to remove the window.  Uses PCW primatives.      */
  275. /**********************************************************/
  276.  
  277. static void close_window(int ur,int uc, int lr, int lc) {
  278.  
  279.    int far  *scrnptr;
  280.    unsigned offset, scrnseg;
  281.    int      rows,cols,page,pagesize;
  282.  
  283.    rows     = (lr - ur) + 1;
  284.    cols     = (lc - uc) + 1;
  285.    page     = getpage();
  286.    pagesize = getpagesize();
  287.    scrnseg  = getscrnseg();
  288.    offset   = MK_SCRNOFF(ur,uc);
  289.    scrnptr  = (int far *) MK_FP(scrnseg,offset);
  290.    RestoreScrn(rows, cols, scrnptr, _int24buf_);
  291. }
  292.